package utility

import (
	"bytes"
	"fmt"
	"hash/crc32"
	"net/url"
	"runtime"
	"strconv"
)

/**
* 捕获异常try...catch
* 用法示例：
  defer try.CatchException(func(e interface{}) {
      log.Println(e)
  })
*/
func CatchException(handle func(e interface{})) {
	if err := recover(); err != nil {
		e := printStackTrace(err)
		handle(e)
	}
}

// 打印堆栈信息
func printStackTrace(err interface{}) string {
	buf := new(bytes.Buffer)
	fmt.Fprintf(buf, "%v\n", err)
	for i := 1; ; i++ {
		pc, file, line, ok := runtime.Caller(i)
		if !ok {
			break
		}
		fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
	}
	return buf.String()
}

func HandleHead(heads map[string][]string) (map[string]string, error) {
	head := make(map[string]string, len(heads))
	for key, fields := range heads {
		newField := ""
		for _, field := range fields {
			subfield, _ := url.QueryUnescape(field)
			newField = newField + subfield + ","
		}
		newField = newField[0 : len(newField)-1]
		head[key] = newField
	}
	if _, ok := head["X-Tenant-Id"]; ok {
		return head, nil
	} else {
		return nil, fmt.Errorf("无　租户id !")
	}
}

// String hashes a string to a unique hashcode.
//
// crc32 returns a uint32, but for our use we need
// and non negative integer. Here we cast to an integer
// and invert it if the result is negative.
func GetStringHash(s string) string {
	v := int(crc32.ChecksumIEEE([]byte(s)))
	if v >= 0 {
		return strconv.Itoa(v)
	}
	if -v >= 0 {
		return strconv.Itoa(-v)
	}
	// v == MinInt
	return "0"
}

func Min(a , b int64) int64 {
	if a>b{
		return  b
	}
	return a
}